1 module hunt.templates.match; 2 3 import std.regex; 4 import std.string; 5 import std.traits; 6 import std.stdio; 7 import std.conv; 8 import std.algorithm.sorting; 9 10 import hunt.templates.rule; 11 12 class Match 13 { 14 string _pattern; 15 public: 16 this() 17 { 18 } 19 20 this(string pattern) 21 { 22 _pattern = pattern; 23 } 24 25 void set_pattern(string pat) 26 { 27 _pattern = pat; 28 } 29 30 @property string pattern() 31 { 32 return _pattern; 33 } 34 35 string str(int i = 0) 36 { 37 return string.init; 38 } 39 40 string prefix() 41 { 42 writeln("-----debug------", __LINE__); 43 return string.init; 44 } 45 46 string suffix() 47 { 48 writeln("-----debug------", __LINE__); 49 return string.init; 50 } 51 52 size_t position() 53 { 54 writeln("-----debug------", __LINE__); 55 return 0; 56 } 57 58 size_t end_position() 59 { 60 writeln("-----debug------", __LINE__); 61 return 0; 62 } 63 64 bool found() 65 { 66 //writeln("-----debug------", __LINE__); 67 return false; 68 } 69 } 70 71 class MatchType(T, R = string) : Match 72 { 73 T type_; 74 RegexMatch!(R) _allm; 75 Captures!(R) _firstm; 76 size_t offset_ = 0; 77 public: 78 this() 79 { 80 super(); 81 } 82 83 this(size_t cur, string pattern = string.init) 84 { 85 super(pattern); 86 offset_ = cur; 87 } 88 89 void setMatchResult(ref RegexMatch!(R) rm) 90 { 91 _allm = rm; 92 } 93 94 @property RegexMatch!(R) match() 95 { 96 return _allm; 97 } 98 99 void setMatchFirst(ref Captures!(R) fm) 100 { 101 _firstm = fm; 102 } 103 104 @property Captures!(R) firstMatch() 105 { 106 return _firstm; 107 } 108 109 void set_type(T type) 110 { 111 type_ = type; 112 } 113 114 @property T type() const 115 { 116 return type_; 117 } 118 119 @property bool empty() 120 { 121 return _allm.empty && _firstm.empty; 122 } 123 124 override bool found() 125 { 126 return !empty; 127 } 128 129 @property size_t size() 130 { 131 return _allm.front.length; 132 } 133 134 override string str(int i = 0) 135 { 136 if (i >= _allm.front.length) 137 return string.init; 138 return _allm.front[i]; 139 } 140 141 override string prefix() 142 { 143 return _allm.front.pre; 144 } 145 146 override string suffix() 147 { 148 return _allm.front.post; 149 } 150 151 override size_t position() 152 { 153 return offset_ + prefix.length; 154 } 155 156 override size_t end_position() 157 { 158 return position() + str(0).length; 159 } 160 161 } 162 163 class MatchClosed 164 { 165 public: 166 Match _open_match, _close_match; 167 168 this() 169 { 170 _open_match = new Match(); 171 _close_match = new Match(); 172 } 173 174 this(Match open_match, Match close_match) 175 { 176 _open_match = open_match; 177 _close_match = close_match; 178 } 179 180 size_t position() 181 { 182 return _open_match.position(); 183 } 184 185 size_t end_position() 186 { 187 return _close_match.end_position(); 188 } 189 190 size_t length() 191 { 192 return _close_match.end_position() - _open_match.position(); 193 } 194 195 bool found() 196 { 197 return _open_match.found() && _close_match.found(); 198 } 199 200 string prefix() 201 { 202 return _open_match.prefix(); 203 } 204 205 string suffix() 206 { 207 return _close_match.suffix(); 208 } 209 210 string outer() 211 { 212 return _open_match.str(0) ~ _open_match.suffix()[0 .. _close_match.end_position() - _open_match.end_position()]; 213 } 214 215 string inner() 216 { 217 //writeln("close pos : ", _close_match.position(), " open end : ", 218 // _open_match.end_position()); 219 return _open_match.suffix()[0 .. _close_match.position() - _open_match.end_position()]; 220 } 221 } 222 223 class RegexObj 224 { 225 226 string _pattern; 227 228 public: 229 this(string pattern) 230 { 231 _pattern = pattern; 232 } 233 234 @property string pattern() 235 { 236 return _pattern; 237 } 238 239 static auto search(string input, string pattern, size_t pos = 0) 240 { 241 MatchType!(string) m = new MatchType!(string)(pos, pattern); 242 auto res = matchAll(pos > 0 ? input[pos .. $] : input, regex(pattern)); 243 m.setMatchResult(res); 244 return m; 245 } 246 247 static auto search_first(string input, string pattern, size_t pos = 0) 248 { 249 MatchType!(string) m = new MatchType!(string)(pos, pattern); 250 auto res = matchFirst(pos > 0 ? input[pos .. $] : input, regex(pattern)); 251 m.setMatchFirst(res); 252 return m; 253 } 254 255 static auto search_all(string input, size_t pos = 0) 256 { 257 MatchType!(Delimiter) m = new MatchType!(Delimiter)(pos); 258 string[] patterns; 259 Delimiter[int] sort_key; 260 int i = 1; 261 foreach (Delimiter k, string v; regex_map_delimiters) 262 { 263 patterns ~= v; 264 sort_key[i] = k; 265 i++; 266 } 267 auto res = matchAll(pos > 0 ? input[pos .. $] : input, regex(patterns)); 268 m.setMatchResult(res); 269 if (!res.empty) 270 { 271 auto idx = res.front.whichPattern; 272 //writeln("--patterns :",patterns); 273 274 if (idx in sort_key) 275 { 276 m.set_type(sort_key[idx]); 277 m.set_pattern(regex_map_delimiters[m.type]); 278 //writeln("--seach first pattern :", m.pattern); 279 } 280 } 281 282 return m; 283 } 284 285 static auto match(T)(string input, string[T] map, size_t pos = 0) 286 { 287 auto keys = map.keys; 288 sort!("a < b")(keys); 289 foreach(e;keys) 290 { 291 auto v =map[e]; 292 auto res = matchAll(pos > 0 ? input[pos .. $] : input, regex(v)); 293 if (!res.empty) 294 { 295 MatchType!(T) mt = new MatchType!(T)(pos, v); 296 mt.setMatchResult(res); 297 mt.set_type(e); 298 //writeln("--match pattern :", v, " --->type : ", e); 299 return mt; 300 } 301 } 302 //writeln("--no match pattern "); 303 MatchType!(T) mt = new MatchType!(T)(pos); 304 return mt; 305 } 306 307 static MatchClosed search_closed_on_level(string input, string regex_statement, 308 string regex_level_up, string regex_level_down, string regex_search, Match open_match) 309 { 310 311 int level = 0; 312 size_t current_position = open_match.end_position(); 313 auto match_delimiter = search(input, regex_statement, current_position); 314 while (match_delimiter.found()) 315 { 316 //writeln("---current_position : ",current_position); 317 //writeln("---current delimiter: ",match_delimiter.str(0)); 318 current_position = match_delimiter.end_position(); 319 string inner = match_delimiter.str(1); 320 if (search(inner, regex_search).found() && level == 0) 321 { 322 break; 323 } 324 if (search(inner, regex_level_up).found()) 325 { 326 level += 1; 327 } 328 else if (search(inner, regex_level_down).found()) 329 { 330 level -= 1; 331 } 332 333 if (level < 0) 334 { 335 //writeln("-----level<0------", __LINE__); 336 return new MatchClosed(); 337 } 338 match_delimiter = search(input, regex_statement, current_position); 339 } 340 //writeln("-----close match ---end pos---",match_delimiter.end_position(),"---level : ",level); 341 return new MatchClosed(open_match, match_delimiter); 342 } 343 344 static MatchClosed search_closed(string input, string regex_statement, 345 string regex_open, string regex_close, Match open_match) 346 { 347 return search_closed_on_level(input, regex_statement, regex_open, 348 regex_close, regex_close, open_match); 349 } 350 }